﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Model
{
    public sealed class FaceInputerResult
    {
        public Surface3d Surface;
        public LcElement Element;
        public Vector3 SnapPoint;
        public Raycaster.Intersection Intersection { get; set; }
    }
    public class SurfaceInputer3d : Inputer3d
    {
        private FaceInputerResult inputp;
        private string option;
        private string prompt;
        public Snap3dRuntime SnapRuntime;
        private Mesh planeSurface;
        private Material planeMaterial = new MeshBasicMaterial { color = new Color(0x00AAAA), polygonOffset = true, polygonOffsetFactor = -1 };
        public SurfaceInputer3d(IDocumentEditor docEditor) : base(docEditor)
        {
            this.SnapRuntime = this.modelEditRt.Snap3DRuntime;
        }
        public async Task<InputResult3d> Execute(string prompt)
        {
            inputp = null;
            option = null;
            this.prompt = prompt + "鼠标选取平面";
            this.commandCtrl.SetAlternateCommandState(false);
            this.Reset();
            this.AttachEvents();
            Prompt(this.prompt);
            this.SnapRuntime.StartSnaping(SnapFilterType.Mesh);
            await WaitFinish();
            this.SnapRuntime.EndSnaping();
            this.planeSurface?.removeFromParent();
            this.DetachEvents();
            this.commandCtrl.SetAlternateCommandState(true);
            //this.commandCtrl.WriteInfo(string.Empty);
            if (this.isCancelled)
                return new InputResult3d { IsCancelled = true };
            else
                return new InputResult3d(inputp, option) { };
        }
        protected override void OnRuntimeMouseDown(MouseEventRuntime e)
        {
            if (!this.isInputed && e.Button == LcMouseButtons.Left)
            {
                if (this.SnapRuntime.SnapPointResult?.Intersection != null)
                {
                    var intersection = this.SnapRuntime.SnapPointResult.Intersection;
                    var solid = intersection.target.ext["Element"] as LcSolid3d;
                    solid.Solid.Topoable = true;
                    var topoModel = solid.Solid.TopoFaceModel;
                    var face = topoModel.Surfaces[intersection.face.materialIndex];
                    if (face != null)
                        this.inputp = new FaceInputerResult { Surface = face, Element = solid, SnapPoint = intersection.point, Intersection = intersection };
                }
                this.commandCtrl.WriteInfo(this.commandCtrl.GetPrompt());
                if (this.inputp == null)
                    return;
                this.Finish();
            }
        }
        private Tuple<int, int> meshIdGrpIdx = null;
        protected override void OnRuntimeMouseMove(MouseEventRuntime e)
        {
            if (this.SnapRuntime.SnapPointResult?.Intersection != null)
            {
                var intersection = this.SnapRuntime.SnapPointResult.Intersection;
                var mesh = intersection.target as Mesh;
                var grpIdx = intersection.face.materialIndex;

                if (meshIdGrpIdx == null || (meshIdGrpIdx.Item1 != mesh.id || meshIdGrpIdx.Item2 != grpIdx))
                {
                    meshIdGrpIdx = new Tuple<int, int>(mesh.id, grpIdx);
                    if (planeSurface != null)
                        planeSurface.removeFromParent();
                    var geo = mesh.geometry.clone();
                    geo.clearGroups();
                    var grp = mesh.geometry.groups[grpIdx].Clone();
                    grp.MaterialIndex = 0;
                    geo.groups.Add(grp);
                    planeSurface = new Mesh(geo, planeMaterial);
                    planeSurface.layers.set(Model3DEditRuntime.UnSelectChannel);
                    mesh.parent.add(planeSurface);
                }
            }
        }
        protected override void OnInputBoxKeyDown(KeyEventRuntime e)
        {
            base.OnInputBoxKeyDown(e);
        }
    }
}
